<?php
/**
 * Created by PhpStorm.
 * User: leo
 * Date: 16/4/11
 * Time: 下午6:36
 * Describe:
 */

namespace services\models;

use common\models\OrderDiscount;
use services\models\OrderInfo;
use Yii;
use yii\base\Exception;
use yii\base\Model;


/**
 * Class Order
 * @package services\models
 * @property \services\models\MemberInfoBestry $_memberInfoBestry
 * @property \services\models\MemberAddress    $_address
 * @property mixed                             score
 * @property int                               $ship_amount_discount
 *
 */
class Order extends Model
{

    public $source;
    public $order_sn;
    public $order_info_id = null;
    public $bestry_uid;
    public $cart_ids      = [];
    public $goods_amount  = 0;
    public $order_amount  = 0;
    public $member_money  = 0;
    public $try_coin      = 0;
    public $reduce_amount = 0;
    public $member_address_id;

    public $ship_amount_try_coin     = 0;
    public $use_coin_for_ship_amount = 0;
    public $ship_amount              = 0;


    protected $_address          = null;
    protected $_memberInfoBestry = null;
    public    $_score            = 0;

    private $_productsInCart;

    public $money_convery_to_money = 100;
    public $ship_amount_discount   = 0;
    public $sms_confirm_code       = null;

    public $payed = false;

    protected $_discount_msg = [];

    public $goods_amount_sale = 0;
    public $try_coin_sale     = 0;
    public $redis;

    public function init()
    {
        $this->source = OrderInfo::$SOURCE_PC;
        $this->redis  = Yii::$app->redis_goods;
        parent::init();
    }

    public function rules()
    {
        return [
            [['member_address_id', 'bestry_uid'], 'integer'],
            [['member_money', 'cart_ids', 'bestry_uid'], 'required'],
            ['member_money', 'number'],
            ['bestry_uid', 'validateCustom'],
            ['bestry_uid', 'validateAddress'],
            ['bestry_uid', 'validateMobile'],
            ['member_money', 'validateMoney'],
        ];
    }

    public function validateMoney()
    {
        if ($this->order_amount + $this->ship_amount_discount < 0) {
            $this->addError('ship_amount_try_coin', '订单金额无需扣除');
        }
    }

    /**
     * user info
     * @return array|\common\models\MemberInfoBestry|null
     * @throws Exception
     */
    public function getMemberInfoBestry()
    {

        if (!empty($this->_memberInfoBestry))
            return $this->_memberInfoBestry;

        if (empty($this->bestry_uid)) {
            $this->addError('bestry_uid', '缺少属性bestry_uid');
            return null;
        }

        try {
            $tmp = $this->_memberInfoBestry = MemberInfoBestry::find()
                                                              ->innerJoinWith('memberInfo')
                                                              ->where(['uid' => $this->bestry_uid])
                                                              ->one();
            return $tmp;

        } catch (Exception $e) {
            return null;
        }
    }

    /*
     * 用户try coin total
     */
    /**
     * @return mixed
     */
    public function getScore()
    {
        if (empty($this->_score)) {
            if (!empty($this->memberInfoBestry)) {
                return $this->_score = $this->memberInfoBestry->memberInfo->score;
            } else
                return 0;
        }
        return $this->_score;
    }


    /**
     * 取得购物车内商品
     * @return array|\common\models\Cart[]|mixed
     */
    public function getProductsInCart()
    {
        if (!empty($this->_productsInCart))
            return $this->_productsInCart;

        $this->_productsInCart = Cart::find()
                                     ->innerJoinWith('product')
                                     ->innerJoinWith('productStock')
                                     ->innerJoinWith('goodsDetail')
                                     ->innerJoinWith('goods')
                                     ->where(['bestry_uid' => $this->bestry_uid])
                                     ->andFilterWhere(['in', 'cart_id', $this->cart_ids])
                                     ->all();

        return $this->_productsInCart;

    }

    /**
     * 取得用户地址
     * @return string|MemberAddress
     */
    public function getAddress()
    {
        if ($this->_address !== null) {
            return $this->_address;
        }
        if ($this->member_address_id === null) {
            $this->_address          = MemberAddress::find()->byDefaultAddress($this->bestry_uid);
            $this->member_address_id = $this->_address->uid;
            return $this->_address;
        }
        $this->_address = MemberAddress::find()->getAddress($this->bestry_uid, $this->member_address_id);
        return $this->_address;
    }

    /**
     *
     */
    public function validateAddress()
    {
        if (empty($this->address)) {
            $this->addError('member_address_id', '请选择地址');
            $this->ship_amount_discount = $this->ship_amount = 0;
        } else {
            $this->ship_amount_discount = $this->ship_amount = $this->address->express_charge;
        }


    }

    public function validateMobile()
    {
        $lktMember = MemberInfo::cache($this->memberInfoBestry->lkt_uid);
        if (!$lktMember->cell || empty($lktMember->cell_jh_num)) {
            $this->addError('cell', '请先绑定手机');
        }
        if ($this->member_money) {
            if (!$this->sms_confirm_code) {
                $this->addError('cell', '请输入验证码.');
            } elseif ($this->sms_confirm_code != MemberInfo::getCellCode($lktMember->cell)) {
                $this->addError('cell', '验证码不正确.');
            }

        }
    }

    /**
     * 校验订单
     */
    public function validateCustom()
    {
        if (empty($this->bestry_uid)) {
            $this->addError('bestry_uid', '用户未登录');
        }

        if (empty($this->cart_ids)) {
            $this->addError('fatal', '购物车没有结算商品');
        }
        if (count($this->ProductsInCart) != count($this->cart_ids)) {
            $this->addError('fatal', '商品信息变更，请返回购物车修改');
        }

        foreach ($this->ProductsInCart as $product) {
            /**
             * 下架商品
             */
            if ($product->product->sale_status == Product::$_SALE_STATUS_OFF_SHELF) {
                $this->addError($product->product_id, $product->goodsDetail->goods_name . '已下架请重新选择');
                continue;
            }

            /**
             * 库存不能小于购买数量
             */
            if ($product->number > $product->productStock->stock) {
                $this->addError($product->product_id, $product->goodsDetail->goods_name . '库存不足请重新选择');
                continue;
            }
            /*if ($product->goods->status == Goods::$_STATUS_OFF ) {
                 $this->addError($product->product_id, $product->goodsDetail->goods_name . '已下架');
                 continue;
             }*/

            /**
             * 试用商品 只能购买一件 ,增加try_coin支付数量
             * 销售商品 累加money支付数
             *
             */
            if ($product->product->type == Product::$_TYPE_TRY) {
                if ($product->number > 1) {
                    $this->addError($product->product_id, ($product->goodsDetail->goods_name).'为免费申领商品，只能领取一件');
                }

                if (Goods::tryGoodsConfirm($product->goods_id, $this->bestry_uid)) {
                    $this->addError($product->product_id, "您已经申领过“".($product->goodsDetail->goods_name)."”，不可重复申领");
                }
                if (!$product->product->checkRegisterLimt($this->memberInfoBestry->memberInfo)) {
                    $this->addErrors($product->product->getErrors());
                }
                if ($product->product->price_type == Product::$_PRICE_TYPE_TRY) {
                    $this->try_coin += $product->product->try_price * $product->number;
                } else {
                    $this->goods_amount += $product->product->sale_price * $product->number;
                }
            }
            if ($product->product->type == Product::$_TYPE_SALE) {
                if ($product->product->price_type == Product::$_PRICE_TYPE_TRY) {
                    $this->try_coin += $product->product->try_price * $product->number;
                    $this->try_coin_sale += $product->product->try_price * $product->number;
                } else {
                    $this->goods_amount += $product->product->sale_price * $product->number;
                    $this->goods_amount_sale += $product->product->sale_price * $product->number;

                }
            }
        }
        #$this->validateAddress();
        $this->order_amount = $this->goods_amount - $this->member_money - $this->reduce_amount;

        /**
         * 判断try_coin是否充足,且当前有试豆商品
         */
        if ($this->score < $this->try_coin && $this->try_coin > 0) {
            $this->addError('try_coin', "您的试豆不足,请适当删除试豆商品");
        }

        /**
         * 判断用户余额是否充足
         */
        if ($this->member_money > 0) {
            if ($this->memberInfoBestry->member_money < $this->member_money) {
                $this->addError('member_money', "您的余额不足");
            }
        }


    }

    public function format()
    {
        $this->order_amount         = Yii::$app->formatter->asDecimal($this->order_amount, 2);
        $this->goods_amount         = Yii::$app->formatter->asDecimal($this->goods_amount, 2);
        $this->ship_amount          = Yii::$app->formatter->asDecimal($this->ship_amount, 2);
        $this->ship_amount_discount = Yii::$app->formatter->asDecimal($this->ship_amount_discount, 2);
        $this->reduce_amount        = Yii::$app->formatter->asDecimal($this->reduce_amount, 2);
    }

    /**
     * 保存订单
     *
     * @return bool
     * @throws \Exception
     * @throws \yii\db\Exception
     */
    public function saveOrder()
    {

        $transaction = OrderInfo::getDb()->beginTransaction();
        try {

            $order                       = new OrderInfo();
            $order->source               = $this->source;
            $order->bestry_uid           = $this->bestry_uid;
            $order->goods_amount         = $this->goods_amount;
            $order->order_amount         = $this->order_amount;
            $order->member_money         = $this->member_money;
            $order->reduce_amount        = $this->reduce_amount;
            $order->ship_amount          = $this->ship_amount_discount;
            $order->try_coin             = $this->try_coin;
            $order->ship_amount_try_coin = $this->ship_amount_try_coin;
            if ($order->order_amount == 0) {
                $order->pay_status = OrderInfo::$PAY_STATUS_SUCCESS;
                $order->status     = OrderInfo::$STATUS_PAYED;
                $this->payed       = true;
                if ($this->member_money) {
                    /* 订单金额为0, 余额不为0, 支付方式为余额 */
                    $order->pay_id   = OrderInfo::$PAY_TYPE_BALANCE;
                    $order->pay_name = OrderInfo::$PAY_TYPE_DESC[$order->pay_id];

                }
                if ($this->member_money == 0 && $this->try_coin) {
                    /* 余额为0, 订单金额为0 试豆不为0 支付方式为试豆 */
                    $order->pay_id   = OrderInfo::$PAY_TYPE_COIN;
                    $order->pay_name = OrderInfo::$PAY_TYPE_DESC[$order->pay_id];
                }
            }


            $result = $order->save();


            if (!$result) {
                $transaction->rollBack();
                $this->addError('order', '下单失败1');
                #var_dump($order->getErrors());
                return false;
            }


            /*save product to order_goods table.*/
            /** @var Cart $item */
            foreach ($this->ProductsInCart as $item) {
                try {

                    $orderGoods                = new OrderGoods();
                    $orderGoods->order_info_id = $order->order_info_id;
                    $orderGoods->goods_id      = $item->goods_id;
                    $orderGoods->product_id    = $item->product_id;
                    $orderGoods->bestry_uid    = $this->bestry_uid;
                    $orderGoods->buy_number    = $item->number;
                    if ($item->product->price_type == Product::$_PRICE_TYPE_TRY) {
                        $try_price  = $item->product->try_price;
                        $sale_price = 0;
                    } else {
                        $sale_price = $item->product->sale_price;
                        $try_price  = 0;
                    }
                    $orderGoods->buy_price        = $sale_price;
                    $orderGoods->free_gift        = OrderGoods::$_GIFT_NO;
                    $orderGoods->commented        = OrderGoods::$_COMMENTED_HAVE_NOT;
                    $orderGoods->activity_id      = 0;
                    $orderGoods->activity_type_id = 0;
                    $orderGoods->price_type       = $item->product->type;
                    $orderGoods->try_coin         = $try_price;
                    $orderGoods->goodsName        = $item->goodsDetail->goods_name;



                    if (!$orderGoods->save()) {
                        $this->addError($item->product_id, '下单失败2');
                        $transaction->rollBack();
                        return false;

                    }
                    if ($orderGoods->hasErrors()) {
                        foreach ($orderGoods->getErrors() as $k => $v) {
                            $this->addError($k, $v);
                            $transaction->rollBack();
                            return false;
                        }
                    }


                    /*ProductStock::updateAllCounters(['stock' => -$orderGoods->buy_number, 'sale_num' => $item->number], ['product_id' => $orderGoods->product_id]);
                    $stock = ProductStock::find()->where(['product_id' => $orderGoods->product_id])->select(['stock'])->scalar();
                    if ($stock < 0) {
                        $this->addError($item->product_id, '下单失败, ' . $item->goodsDetail->goods_name . '已经卖光.');
                        $transaction->rollBack();
                        return false;
                    }*/


                } catch (Exception $e) {
                    $this->addError($item->product_id, '下单失败3');
                    $transaction->rollBack();
                    return false;
                }
                if ($this->hasErrors()) {

                    $this->addError($item->product_id, '下单失败4');
                    $transaction->rollBack();
                    return false;
                }

            }


            try {#保存收货地址
                $oe                = new OrderExpress();
                $oe->order_info_id = $order->order_info_id;

                $oe->consignee = $this->address->consignee;

                $oe->province      = $this->address->s1;
                $oe->city          = $this->address->s2;
                $oe->county        = $this->address->s3;
                $oe->telephone     = $this->address->tel1;
                $oe->mobile_phone  = $this->address->cell;
                $oe->address       = $this->address->address;
                $oe->zip           = $this->address->zipcode;
                $oe->delivery_time = 1; //todo:送货时间, 1,2,3

                $oe->save();
                if ($oe->hasErrors()) {
                    $this->addError('member_address_id', '送货地址错误 ');
                    $transaction->rollBack();
                    return false;
                }
            } catch (Exception $e) {

                $transaction->rollBack();
                $this->addError('member_address_id', '送货地址错误 ');
                return false;
            }
            /**
             * 扣试豆
             */
            if ($this->try_coin) {
                try {
                    $try_coin = $order->try_coin - $order->ship_amount_try_coin;
                    MemberScore::subScore($try_coin, "订单: {$order->order_sn} 消耗 {$try_coin} 试豆", $this->_memberInfoBestry->lkt_uid);
                } catch (Exception $e) {
                    $this->addError('try_coin', '扣除试豆失败');
                    $transaction->rollBack();
                    return false;
                }
            }
            /**
             * 扣试豆运费
             */
            if ($this->ship_amount_try_coin > 0 && $this->use_coin_for_ship_amount) {
                try {
                    MemberScore::subScore($this->ship_amount_try_coin, "订单: {$order->order_sn} 消耗 {$this->ship_amount_try_coin} 试豆抵扣邮费", $this->_memberInfoBestry->lkt_uid);
                } catch (Exception $e) {
                    $this->addError('try_coin', '扣除试豆抵邮费失败');
                    $transaction->rollBack();
                    return false;
                }
            }
            if (MemberScore::getScore($this->memberInfoBestry->lkt_uid) < 0) {
                $this->addError('try_coin', '试豆不足');
                $transaction->rollBack();
                return false;
            }
            /**
             * 扣用户余额
             */
            if ($this->member_money) {
                MemberInfoBestry::updateAllCounters(['member_money' => -$this->member_money], ['uid' => $this->bestry_uid]);
                $this->_memberInfoBestry = MemberInfoBestry::findOne(['uid' => $this->bestry_uid]);
                if ($this->_memberInfoBestry->member_money < 0) {
                    $this->addError('member_money', '您的余额不足');
                    $transaction->rollBack();
                    return false;
                }
                $mt                = new MoneyTable();
                $mt->member_uid    = $this->bestry_uid;
                $mt->order_info_id = $order->order_info_id;
                $mt->money         = -$this->member_money;
                $mt->end_money     = $this->_memberInfoBestry->member_money;
                $mt->start_money   = $mt->end_money - $mt->money;

                $mt->memo = "订单 $order->order_sn 余额支付";
                $mt->type = MoneyTable::$_TYPE_USER_ORDER;
                if (!$mt->save()) {
                    $this->addError('member_money', '扣除余额出错');
                    $transaction->rollBack();
                    return false;
                }


            }
            /** @var OrderDiscount $item */
            foreach ($this->getDiscountMsg() as $item) {
                try {
                    $item->order_info_id = $order->order_info_id;
                    $item->save();
                    unset($item);
                } catch (Exception $e) {
                    $this->addError('discount', '优惠打折写入失败');
                    $transaction->rollBack();
                    return false;
                }
            }

            /*delete records in cart*/
            try {
                Cart::deleteAll(['in', 'cart_id', $this->cart_ids]);
            } catch (Exception $e) {
                $this->addError('cart_ids', '删除购物车商品出错.');
                $transaction->rollBack();
                return false;
            }

            /*write order log*/
            try {
                $ol = new OrderLog();
                #$ol->uid = $this->bestry_uid;
                $ol->order_info_id    = $order->order_info_id;
                $ol->start_pay_status = OrderInfo::$PAY_STATUS[OrderInfo::$PAY_STATUS_WAIT];
                $ol->end_pay_status   = OrderInfo::$PAY_STATUS[OrderInfo::$PAY_STATUS_WAIT];
                $ol->start_status     = OrderInfo::$STATUS_DESC[OrderInfo::$STATUS_ORDER_CREATED];//$order->status;
                $ol->end_status       = OrderInfo::$STATUS_DESC[OrderInfo::$STATUS_ORDER_CREATED];//$order->status;


                if (!$ol->save()) {
                    $transaction->rollBack();

                    $this->addError('log', '日志保存错误1');
                    return false;
                }

            } catch (\Exception $e) {
                $transaction->rollBack();
                $this->addError('log', '日志保存错误2');
                return false;
            }

            $transaction->commit();
            /**
             * 生成订单成功后, redis减库存
             * @var Cart $item
             */
            foreach ($this->ProductsInCart as $item) {
                $this->redis->decrby('p_stock_' . $item->product_id, $item->number);
                if ($item->product->type == Product::$_TYPE_TRY) {
                    Goods::tryGoodsAdd($item->goods_id, $this->bestry_uid);
                }
            }
        } catch (Exception $e) {
            $this->addError('save', '保存订单出错' . $e->getMessage());
            $transaction->rollBack();
            return false;
        }
        $this->order_sn      = $order->order_sn;
        $this->order_info_id = $order->order_info_id;

        return true;
    }

    /**
     * 取消订单
     * @return bool
     * @throws \yii\db\Exception
     */
    public function cancelOrder()
    {
        $transaction = OrderInfo::getDb()->beginTransaction();
        try {

            /** @var \services\models\OrderInfo $orderInfo */
            $orderInfo = OrderInfo::find()->byPrimary($this->order_info_id);
            if (empty($orderInfo)) {
                $this->addError('order_info_id', '订单没找到');
            }

            if ($this->bestry_uid > 0 && $orderInfo->bestry_uid != $this->bestry_uid) {
                $this->addError('bestry_uid', '用户不能为空.');
                return false;
            }
            /*订单状态为配货中, 不能退货*/
            if ($orderInfo->status >= OrderInfo::$STATUS_CONFIRM) {
                $this->addError('order_info_id', '订单状态为配货中, 不能退货');

                return false;
            }
            /** @var OrderGoods $od */
            foreach ($orderInfo->orderGoods as $od) {
                ProductStock::updateAllCounters(['stock' => $od->buy_number, 'sale_num' => -$od->buy_number], ['product_id' => $od->product_id]);
            }

            $moneyBack = 0;
            /*退余额至帐号*/
            if ($orderInfo->pay_status == OrderInfo::$PAY_STATUS_SUCCESS) {
                $moneyBack += abs($orderInfo->order_amount);
            }
            /*退还余额*/
            if ($orderInfo->member_money) {
                $moneyBack += abs($orderInfo->member_money);
            }
            if ($moneyBack > 0) {
                /** @var MemberInfoBestry $member */
                $member = MemberInfoBestry::findOne(['uid' => $orderInfo->bestry_uid]);

                if (!MemberInfoBestry::updateAllCounters(['member_money' => $moneyBack],
                                                         ['uid' => $orderInfo->bestry_uid]
                )
                ) {
                    $this->addError('order_info_id', '退余额出错');
                    $transaction->rollBack();
                    return false;
                }
                try {

                    $mt                = new MoneyTable();
                    $mt->member_uid    = $orderInfo->bestry_uid;
                    $mt->order_info_id = $orderInfo->order_info_id;
                    $mt->money         = $moneyBack;
                    $mt->end_money     = $member->member_money + $moneyBack;
                    $mt->start_money   = $member->member_money;
                    $mt->memo          = "订单 $orderInfo->order_sn 取消, 余额退还";
                    $mt->type          = MoneyTable::$_TYPE_CANCEL;
                    if (!$mt->save()) {
                        $this->addError('order_info_id', '退余额出错');

                        $transaction->rollBack();
                        return false;
                    }
                } catch (Exception $e) {

                    $this->addError('order_info_id', '退余额出错');

                    $transaction->rollBack();
                    return false;
                }
            }

            /*退还试豆*/
            if ($orderInfo->try_coin > 0) {
                if (!MemberScore::addScore($orderInfo->try_coin, "订单: {$orderInfo->order_sn} 取消, 退还 {$orderInfo->try_coin} 试豆",
                                           $orderInfo->memberInfoBestry->lkt_uid)
                ) {
                    $this->addError('order_info_id', '退试豆出错');
                    $transaction->rollBack();
                    return false;
                }
            }

            /*write order log*/
            try {

                $ol = new OrderLog();

                $ol->order_info_id    = $orderInfo->order_info_id;
                $ol->start_pay_status = OrderInfo::$PAY_STATUS[$orderInfo->pay_status];
                $ol->end_pay_status   = OrderInfo::$PAY_STATUS[$orderInfo->pay_status];
                $ol->start_status     = OrderInfo::$STATUS_DESC[$orderInfo->status];
                $ol->end_status       = OrderInfo::$STATUS_DESC[OrderInfo::$STATUS_ORDER_CANCEL];

                if (!$ol->save()) {
                    $this->addError('bestry_uid', '写入日志失败');
                    $transaction->rollBack();
                    return false;
                }

            } catch (\Exception $e) {
                $this->addError('bestry_uid', '写入日志失败');
                $transaction->rollBack();
                return false;
            }
            $orderInfo->status = OrderInfo::$STATUS_ORDER_CANCEL;

            if (!$orderInfo->save()) {
                $this->addError('order_info_id', '取消订单出错1');
                $transaction->rollBack();

                return false;
            }

            $transaction->commit();
            /**
             * 取消订单成功后, redis加库存
             * @var OrderGoods $item
             */
            foreach ($orderInfo->orderGoods as $item) {
                if ($item->product->type == Product::$_TYPE_TRY) {
                    Goods::tryGoodsRemove($od->goods_id, $orderInfo->bestry_uid);
                }
                $this->redis->incrby('p_stock_' . $item->product_id, $item->buy_number);
            }
        } catch (Exception $e) {
            $this->addError('order_info_id', '取消订单出错2');
            $transaction->rollBack();

            return false;
        }
        return true;
    }


    /**
     * 支付回调更改订单状态
     * @param $order_info_id
     * @return bool
     * @throws \yii\db\Exception
     */
    public static function orderStatusChangePayed($order_info_id)
    {
        return static::orderStatusChange($order_info_id, OrderInfo::$STATUS_PAYED, OrderInfo::$PAY_STATUS_SUCCESS);
    }


    /**
     * 更改订单状态
     *
     * @param int      $order_info_id
     * @param int      $status     订单状态
     * @param null|int $pay_status 支付状态
     * @return true
     * @throws Exception
     * @throws \yii\db\Exception
     */
    public static function orderStatusChange($order_info_id, $status, $pay_status = null)
    {

        if (!key_exists($status, OrderInfo::$STATUS_DESC)) {
            throw new Exception('订单状态不在范围内');
        }
        if ($pay_status !== null && !key_exists($pay_status, OrderInfo::$STATUS_DESC)) {
            throw new Exception('订单支付状态不在范围内');
        }


        $transaction = OrderInfo::getDb()->beginTransaction();

        try {
            /** @var OrderInfo $order */
            $order = OrderInfo::find()->byPrimary($order_info_id);
            if (empty($order)) {
                throw new Exception('订单未找到.');
            }
            $log                   = new OrderLog();
            $log->order_info_id    = $order->order_info_id;
            $log->start_pay_status = OrderInfo::$PAY_STATUS[$order->pay_status];
            $log->start_status     = OrderInfo::$STATUS_DESC[$order->status];

            $log->end_pay_status = OrderInfo::$PAY_STATUS[$pay_status];
            $log->end_status     = OrderInfo::$STATUS_DESC[$status];


            if ($pay_status !== null) {
                $order->pay_status = $pay_status;
            }
            $order->status = $status;
            if (!$order->save() || !$log->save()) {
                $transaction->rollBack();
                throw new Exception('保存状态失败');
            }

            if (OrderInfo::$STATUS_PAYED == $pay_status) {
                try {

                    $ei               = new ExpInfo();
                    $ei->exec_address = '客户';
                    $ei->exec_remark  = '订单已支付，等待确认';
                    $ei->type         = 1;
                    $ei->orderid      = $order->order_sn;
                    if (!$ei->save()) {
                        $transaction->rollBack();
                        throw new Exception('支付成功,增加物流日志失败');
                    }
                } catch (Exception $e) {
                    $transaction->rollBack();
                    throw new Exception('支付成功,增加物流日志失败');
                }

            }


            $transaction->commit();

        } catch (Exception $e) {
            $transaction->rollBack();
            throw $e;
        }
        return true;

    }

    /**
     * 更改订单状态
     *
     * @param int      $order_info_id
     * @param int      $status     订单状态
     * @param null|int $pay_status 支付状态
     * @return true
     * @throws Exception
     * @throws \yii\db\Exception
     */
    public static function orderStatusChangeHistory($order_info_id, $status, $pay_status = null)
    {

        if (!key_exists($status, OrderInfo::$STATUS_DESC)) {
            throw new Exception('订单状态不在范围内');
        }
        if ($pay_status !== null && !key_exists($pay_status, OrderInfo::$STATUS_DESC)) {
            throw new Exception('订单支付状态不在范围内');
        }


        $transaction = \services\models\OrderInfoHistory::getDb()->beginTransaction();

        try {
            /** @var OrderInfo $order */
            $order = \services\models\OrderInfoHistory::find()->byPrimary($order_info_id);
            if (empty($order)) {
                throw new Exception('订单未找到.');
            }
            $log                   = new OrderLog();
            $log->order_info_id    = $order->order_info_id;
            $log->start_pay_status = OrderInfo::$STATUS_DESC[$order->pay_status];
            $log->start_status     = OrderInfo::$STATUS_DESC[$order->status];

            $log->end_pay_status = OrderInfo::$STATUS_DESC[$pay_status];
            $log->end_status     = OrderInfo::$STATUS_DESC[$status];


            if ($pay_status !== null) {
                $order->pay_status = $pay_status;
            }
            $order->status = $status;
            if (!$order->save() || !$log->save()) {
                $transaction->rollBack();
                throw new Exception('保存状态失败');
            }

            if (OrderInfo::$STATUS_PAYED == $pay_status) {
                try {

                    $ei               = new ExpInfo();
                    $ei->exec_address = '客户';
                    $ei->exec_remark  = '订单已支付，等待确认';
                    $ei->type         = 1;
                    $ei->orderid      = $order->order_sn;
                    if (!$ei->save()) {
                        $transaction->rollBack();
                        throw new Exception('支付成功,增加物流日志失败');
                    }
                } catch (Exception $e) {
                    $transaction->rollBack();
                    throw new Exception('支付成功,增加物流日志失败');
                }

            }


            $transaction->commit();

        } catch (Exception $e) {
            $transaction->rollBack();
            throw $e;
        }
        return true;

    }

    /**
     * @return array
     */
    public function getDiscountMsg()
    {
        return $this->_discount_msg;
    }

    /**
     * @param DiscountMessage $discount_msg
     */
    public function addDiscountMsg($discount_msg)
    {
        $this->_discount_msg[] = $discount_msg;
    }

    public function hasDiscount()
    {
        return !empty($this->_discount_msg);
    }

}